import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.TreeMap;

/**
 * 
 * @author Pietro Bua & Rohmin Mirza
 *
 */
public class Apl
{
	private static ArrayList<String> arrWords;
	private static Node trie;
	
	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		//arrWords = readData("doc.txt");
		
		arrWords = new ArrayList<String>();
		arrWords.add("ball");
		arrWords.add("ball");
		arrWords.add("bat");
		arrWords.add("doll");
		arrWords.add("dork");
		arrWords.add("do");
		arrWords.add("send");
		arrWords.add("sense");
		arrWords.add("dorm");
		
		
		// === Insert ===
		trie = new Node( 'X' );
		for(int i=0;i<arrWords.size();i++)
		{
			Data data = new Data( i+1 ); // i+1 = positions in text
			trie.insert(arrWords.get(i),data);
			System.out.println("");
			System.out.println(trie.toString());
			System.out.println("--------------------------------------------------------------------------------");
		}
		
		// === Print ===
		System.out.println("================================================================================");
		System.out.println("Printing whole trie: " + trie.toString());

		// === Search ===
		String str = "do";
		
		System.out.println("Searching: " + str);
		Data toSearch = trie.search(str);
		if( toSearch != null )
		{
			System.out.println("Found: " + toSearch.toString() );
		}
		
		// === Delete ===
		System.out.println("Deleting: " + str );
		trie.delete(str);
		
		// === Search ===
		System.out.println("Searching: " + str);
		Data toSearch2 = trie.search(str);
		if( toSearch2 != null )
		{
			System.out.println("Found: " + toSearch2.toString() );
		}
		
		// === Print ===
		System.out.println("================================================================================");
		System.out.println("Printing whole trie:" + "\r\n" + trie.toString());
				
		// === Alphabetical table ===
		System.out.println("================================================================================");
		System.out.println("Printing the words alphabetically");
		alphabeticalTablePrint( trie );
		
		// === Frequency table ===
		System.out.println("================================================================================");
		System.out.println("Printing the words in frequency");
		frequencyTablePrint( trie );

	}
	
	/**
	 * 
	 * @param words
	 */
	public static void alphabeticalTablePrint( Node node )
	{
		ArrayList<String> allNodes = node.getAllNodes("", new ArrayList<String>() );
		
		Map<String, Integer> alphabeticalWords = new TreeMap<String,Integer>();
		
		for(String str : allNodes )
		{
			if( node.search(str) != null )
			{
				ArrayList<Integer> positions = node.search(str).getPositions();
				if( ! positions.isEmpty() )
				{
					int pos = positions.get(0);
					alphabeticalWords.put(str, pos);
				}
			}
			else
			{
				System.out.println("Not found: " + str);
			}
		}
		
		for( Map.Entry entry : alphabeticalWords.entrySet() )
		{
			System.out.println("[" + entry.getKey() + "] position: " + entry.getValue());
		}
	}
	

	
	/**
	 * 
	 */
	public static void frequencyTablePrint( Node node)
	{
		Map<String, Integer> freqWords = new TreeMap<String, Integer>();
		ArrayList<String> allNodes = node.getAllNodes("", new ArrayList<String>() );
		
		for(int i=0;i<allNodes.size();i++ )
		{
			String word = allNodes.get(i);
			int x = Collections.frequency(allNodes, word);
			if(! freqWords.containsKey(word))
			{
				freqWords.put(word, x);
			}
			else
			{
				//System.out.println("Word already added");
			}
		}

		Map<String, Integer> sortedMap = sortByComparator(freqWords);

		for (Map.Entry entry : sortedMap.entrySet()) {
			System.out.println("[" + entry.getKey() + "] nr of times: " + entry.getValue());
		}
	}
	
	/**
	 * 
	 * @param unsortMap
	 * @return
	 */
	private static Map sortByComparator(Map unsortMap)
	{
		 
		List list = new LinkedList(unsortMap.entrySet());
 
		// sort list based on comparator
		Collections.sort(list, new Comparator() {
			public int compare(Object o1, Object o2) {
				return ((Comparable) ((Map.Entry) (o2)).getValue()).compareTo(((Map.Entry) (o1)).getValue());
			}
		});
 
		// put sorted list into map again
        //LinkedHashMap make sure order in which keys were inserted
		Map sortedMap = new LinkedHashMap();
		for (Iterator it = list.iterator(); it.hasNext();) {
			Map.Entry entry = (Map.Entry) it.next();
			sortedMap.put(entry.getKey(), entry.getValue());
		}
		return sortedMap;
	}
	
	/**
	 * 
	 * @param fileName
	 * @return
	 */
	private static ArrayList<String> readData(String fileName)
	{
		File file = new File(fileName);
		Scanner scanner = null;
		ArrayList<String> ret = new ArrayList<String>();
		try
		{
			scanner = new Scanner(file);
			scanner.useDelimiter(" ");
			while (scanner.hasNextLine())
			{
				Scanner scannerLine = new Scanner(scanner.nextLine());
				while(scannerLine.hasNext())
				{
					String s = scannerLine.next();
					//System.out.println(">" + s + "<");
					if( ! s.contains(" ") )
					{
						ret.add(s);
					}	
				}
				scannerLine.close();
			}
		}
		catch (FileNotFoundException e)
		{
			System.out.println("File not found");
			//e.printStackTrace();
		}
		finally
		{
			scanner.close();
		}

		return ret;
	}

}
